#pragma once
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/time.h>
#include <atomic>
#include <vector>
#include <fstream>
#include <boost/algorithm/string.hpp>

std::string g_path_name = "../temp/";
class PathUtil
{
public:
    static std::string AddSuffix(const std::string& file_name, const std::string& suffix)
    {
        std::string path_name = g_path_name;
        path_name += file_name;
        path_name += suffix;

        return path_name;
    }

    // 文件名拼接为文件路径+后缀的完整文件名
    // 123 -> ../temp/123.cpp

    // 编译用的文件
    static std::string PathSrc(const std::string& file_name)
    {
        return AddSuffix(file_name, ".cpp");
    }

    static std::string PathExe(const std::string& file_name)
    {
        return AddSuffix(file_name, ".exe");
    }

    static std::string PathErr(const std::string& file_name)
    {
        return AddSuffix(file_name, ".compile_err");
    }

    // 运行用的文件
    static std::string Stdin(const std::string& file_name)
    {
        return AddSuffix(file_name, ".stdin");
    }
    static std::string Stdout(const std::string& file_name)
    {
        return AddSuffix(file_name, ".stdout");
    }
    static std::string Stderr(const std::string& file_name)
    {
        return AddSuffix(file_name, ".stderr");
    }
};

class TimeUtil
{
public:
    static std::string GetTimeStamp()
    {
        struct timeval time;
        gettimeofday(&time, nullptr);
        return std::to_string(time.tv_sec);
    }

    static std::string GetTimeStampMs()
    {
        struct timeval time;
        gettimeofday(&time, nullptr);
        return std::to_string(time.tv_sec*1000 + time.tv_usec/1000);
    }
};

class FileUtil
{
public:
    static bool IsFileExists(const std::string& path_name)
    {
        struct stat st;
        if (stat(path_name.c_str(), &st) == 0)
        {
            // 获取成功，文件存在
            return true;
        }

        return false;
    }
    
    static std::string UniqueName()
    {
        static std::atomic_uint id(0);
        id++;

        // 时间戳+原子值确保唯一
        std::string ms = TimeUtil::GetTimeStampMs();
        ms += "_";
        ms += std::to_string(id);

        return ms;
    }

    static bool WriteFile(const std::string& target, const std::string& content)
    {
        std::ofstream out(target);
        if (!out.is_open())
        {
            return false;
        }

        out.write(content.c_str(), content.size());
        out.close();
        return true;
    }

    // 读文件，第三个参数是否加换行
    static bool ReadFile(const std::string& target, std::string* content, bool keep=false)
    {
        content->clear();
        std::ifstream in(target);
        if (!in.is_open())
        {
            return false;
        }

        std::string line;
        while (std::getline(in, line))
        {
            *content += line;
            *content += (keep? "\n":"");
        }

        in.close();
        return true;
    }
};

class StringUtil
{
public:
    void static SplitString(const std::string& str, std::vector<std::string>* target, const std::string sep)
    {
        boost::split((*target), str, boost::is_any_of(sep), boost::algorithm::token_compress_on);
    }
};